package com.google.code.timeeditapplication.model.implementation;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Scanner;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

/**
 * TimeEditCommunicator is a Singleton class that handles communication with
 * Chalmers' TimeEdit server
 * 
 * @author deas
 * 
 */
public class TimeEditCommunicator {
	private static TimeEditCommunicator tEC;
	private ArrayList<SearchResult> result;

	private TimeEditCommunicator() {

	}

	/**
	 * 
	 * @return instance of TimeEditCommunicator
	 */
	public static TimeEditCommunicator getInstance() {
		if (tEC == null) {
			tEC = new TimeEditCommunicator();
		}
		return tEC;
	}

	/**
	 * 
	 * @param searchWord
	 *            Text string to search for
	 * @return results of search
	 * @throws IOException
	 *             on connection problems or bad url (caused by bad searchWord)
	 */
	public void search(final String searchWord) {
		final HttpClient httpclient = new DefaultHttpClient();
		final HttpGet httpget = new HttpGet(
				"https://web.timeedit.se/chalmers_se/db1/timeedit/p/public/objects.html?max=18&fr=t&partajax=t&im=f&sid=3&search_text="
						+ searchWord + "&types=194");
		@SuppressWarnings("hiding")
		final ArrayList<SearchResult> result = new ArrayList<SearchResult>();

		try {
			final HttpResponse response = httpclient.execute(httpget);
			final BufferedReader reader = new BufferedReader(
					new InputStreamReader(response.getEntity().getContent()));

			final Scanner sc = new Scanner(reader);

			sc.useDelimiter("objectbasketitemX");
			sc.next();
			while (sc.hasNext()) {
				sc.useDelimiter("\"");
				sc.next();
				sc.next();
				final String id = sc.next();
				sc.next();
				final String name = sc.next();

				result.add(new SearchResult(name, id));
				sc.useDelimiter("objectbasketitemX");
				sc.next();
			}
		} catch (final ClientProtocolException e) {
			// this shouldn't happen, hopefully it doesn't
		} catch (final IOException e) {
			// this shouldn't happen, hopefully it doesn't
		}

		result.remove(result.size() - 1); // remove dash from end
		this.result = result;
	}

	public ArrayList<SearchResult> getResults() {
		return this.result;
	}

	/**
	 * Downloads schedule from TimeEdit in icalendar format from its id
	 * 
	 * @param id
	 *            SearchResult id for wanted schedule
	 * @param location
	 *            where to save schedule
	 * @throws IOException
	 *             on network error or bad url (caused by bad id)
	 */
	public void downloadSchedule(final String id, final String location)
			throws IOException {
		download(fetchIcalUrl(id), location);
	}

	// fetch the icalendar file url from a SearchResult's id
	private String fetchIcalUrl(final String id) {
		@SuppressWarnings("hiding")
		String result = "";
		final String searchUrl = "https://web.timeedit.se/chalmers_se/db1/timeedit/p/public/reservations.html?sid=3&objects="
				+ id
				+ "&ox=0&types=0&fe=0&mu=t&p=20110829.x,20111231.x#formatlinks"; // the
																					// dates
																					// are
																					// to
																					// be
																					// variable
																					// later
		final HttpClient httpclient = new DefaultHttpClient();
		final HttpGet httpget = new HttpGet(searchUrl);

		try {
			final HttpResponse response = httpclient.execute(httpget);
			final BufferedReader reader = new BufferedReader(
					new InputStreamReader(response.getEntity().getContent()));
			final Scanner sc = new Scanner(reader);

			sc.useDelimiter("https://web.timeedit.se/chalmers_se/db1/timeedit/p/public/reservations.ics?");
			sc.next();
			sc.useDelimiter("\"");
			result = sc.next();
		} catch (final ClientProtocolException e) {
			// Auto-generated catch block
		} catch (final IOException e) {
			// Auto-generated catch block
		}
		return result;
	}

	// download file residing at URL url to location
	private void download(final String url, final String location)
			throws IOException {
		final BufferedInputStream bIS = new java.io.BufferedInputStream(
				new URL(url).openStream());
		final FileOutputStream fOS = new java.io.FileOutputStream(location);
		final BufferedOutputStream bOS = new BufferedOutputStream(fOS, 1024);
		final byte[] data = new byte[1024];
		int x = 0;
		while ((x = bIS.read(data, 0, 1024)) >= 0) {
			bOS.write(data, 0, x);
		}
		bOS.close();
		bIS.close();
	}
}
